

package VisAVisTab;

import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;
import edu.stanford.smi.protege.util.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
import javax.swing.tree.*;



public class QueryPanelPostgres extends JPanel implements ActionListener,DropTargetListener {
    
    PostgresPanel parentPanel;
    OntologyPanel ontPanel;
    OntModel ontModel;
    Vector tablesVector=new Vector();
    Vector fieldsVector=new Vector();
    Vector fieldInfoVector =new Vector();
    Vector criteriaVector = new Vector();
    JList tableList=new JList(tablesVector);
    JList fieldList=new JList(fieldsVector);
    JPopupMenu popupT;
    JPopupMenu popupF;
    JPopupMenu popupC;
    JPopupMenu popupM;
    JMenuItem removeMenuItemT = new JMenuItem("Remove");
    JMenuItem removeMenuItemF = new JMenuItem("Remove");
    JMenuItem removeMenuItemC = new JMenuItem("Remove Entire Row");
    JMenuItem removeMenuItemM = new JMenuItem("Clear Field");
    DefaultTableModel dm = new DefaultTableModel();
    JTable criteriaTable=new JTable(dm);
    JButton mapButton = new JButton("Map!");
    JTextField mapField=new JTextField(20);
    String queryString,basePrefix;
    JScrollPane scrollTable;
    NodeInfo selectedNodeInfo;
    
    
    public QueryPanelPostgres(PostgresPanel panel,OntologyPanel ontPanel) {
        parentPanel=panel;
        this.ontPanel=ontPanel;
        GridBagLayout myLayout=new GridBagLayout();
        GridBagConstraints constraints=new GridBagConstraints();
        setLayout(myLayout);
        
        
        JPanel p1=new JPanel();
        LabeledComponent label=new LabeledComponent("Choose Your Data",p1,false);
        
        
        
        p1.add(new JLabel("Required Tables:", JLabel.LEFT));
        
        JScrollPane tablePane =new JScrollPane(tableList);
        tableList.setToolTipText("The tables involved in the data choosing are shown here");
        tablePane.setPreferredSize(new Dimension(200,50));
        DropTarget dropTargetT=new DropTarget(tableList,this);
        
        p1.add(tablePane);
        
        
        JPanel p2=new JPanel();
        p2.add(new JLabel("Desired Fields:", JLabel.LEFT));
        
        JScrollPane fieldPane =new JScrollPane(fieldList);
        fieldList.setToolTipText("Drop here the columns to which the wanted data belong");
        fieldPane.setPreferredSize(new Dimension(200,100));
        DropTarget dropTargetF=new DropTarget(fieldList,this);
        p2.add(fieldPane);
        
        
        
        JPanel p3=new JPanel();
        p3.add(new JLabel("Conditions:", JLabel.LEFT));
        Vector dummyHeader=new Vector();
        dummyHeader.addElement("Field Name");
        dummyHeader.addElement("Condition");
        
        dm.setDataVector(null,dummyHeader);
        criteriaTable.setShowGrid(false);
        criteriaTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JTextField nonEdit=new JTextField();
        nonEdit.setEditable(false);
        JTextField edit=new JTextField("");
        DropTarget dropTargetE=new DropTarget(edit,this);
        edit.setEditable(true);
        criteriaTable.getColumn("Field Name").setCellEditor(new DefaultCellEditor(nonEdit));
        criteriaTable.getColumn("Condition").setCellEditor(new DefaultCellEditor(edit));
        scrollTable = new JScrollPane(criteriaTable);
        scrollTable.setColumnHeader(null);
        scrollTable.setPreferredSize(new Dimension(250,100));
        
        scrollTable.setToolTipText("To add a condition,drop here the column related");
        criteriaTable.setToolTipText("To add a condition,drop here the column related");
        
        
        DropTarget dropTargetC1=new DropTarget(scrollTable,this);
        DropTarget dropTargetC2=new DropTarget(criteriaTable,this);
        p3.add(scrollTable);
        
        
        JPanel p4=new JPanel();
        p4.add(new JLabel("Map To:"));
        mapField.setEditable(false);
        mapField.setToolTipText("To map a class,drag it from the ontology tree and drop it here");
        DropTarget dropTargetM=new DropTarget(mapField,this);
        p4.add(mapField);
        mapButton.addActionListener(this);
        p4.add(mapButton);
        
        
        
        ontPanel.buildConstraints(constraints,0,0,1,1,100,4,GridBagConstraints.BOTH);
        myLayout.setConstraints(label,constraints);
        add(label);
        
        ontPanel.buildConstraints(constraints,0,1,1,1,0,25,GridBagConstraints.BOTH);
        myLayout.setConstraints(p1,constraints);
        add(p1);
        
        ontPanel.buildConstraints(constraints,0,2,1,1,0,25,GridBagConstraints.BOTH);
        myLayout.setConstraints(p2,constraints);
        add(p2);
        
        ontPanel.buildConstraints(constraints,0,3,1,1,0,25,GridBagConstraints.BOTH);
        myLayout.setConstraints(p3,constraints);
        add(p3);
        
        ontPanel.buildConstraints(constraints,0,4,1,1,0,21,GridBagConstraints.BOTH);
        myLayout.setConstraints(p4,constraints);
        add(p4);
        
        
        
        popupT = new JPopupMenu();
        
        removeMenuItemT.addActionListener(this);
        popupT.add(removeMenuItemT);
        
        popupF = new JPopupMenu();
        
        removeMenuItemF.addActionListener(this);
        popupF.add(removeMenuItemF);
        
        popupC = new JPopupMenu();
        
        removeMenuItemC.addActionListener(this);
        popupC.add(removeMenuItemC);
        
        popupM = new JPopupMenu();
        
        removeMenuItemM.addActionListener(this);
        popupM.add(removeMenuItemM);
        
        //Add listener to components that can bring up popup menus.
        MouseListener popupListenerT = new PopupListener(popupT,tableList);
        tableList.addMouseListener(popupListenerT);
        MouseListener popupListenerF = new PopupListener(popupF,fieldList);
        fieldList.addMouseListener(popupListenerF);
        MouseListener popupListenerC = new PopupListener(popupC,criteriaTable);
        criteriaTable.addMouseListener(popupListenerC);
        MouseListener popupListenerM = new PopupListener(popupM);
        mapField.addMouseListener(popupListenerM);
    }
    
    
    //Handle action methods
    public void actionPerformed(ActionEvent e){
        Object source = e.getSource();
        
        //if Remove in the Table List is pressed
        if (source==removeMenuItemT){
            String tobeRemoved=(String)tableList.getSelectedValue();
            if (tobeRemoved!=null){
                
                int answer=JOptionPane.showConfirmDialog(null,"If you remove this table,all of its fields that have already been added in the desired fields list as well as in the criteria list will be removed.\nDo you want to continue?",
                        "Removing from Table List",
                        JOptionPane.YES_NO_OPTION);
                if (answer==JOptionPane.YES_OPTION){
                    //remove table from the table list
                    tablesVector.remove(tobeRemoved);
                    
                    
                    try{
                        
                        DatabaseMetaData dbMetaData =parentPanel.con.getMetaData();
                        
                        //remove all of its fields in the fieldList and criteria list
                        ResultSet rsColumns = dbMetaData.getColumns(null,null,tobeRemoved,null);
                        boolean bMore = rsColumns.next();
                        while (bMore) {
                            String strColumnName = rsColumns.getString("COLUMN_NAME");
                            for (int i=0;i<fieldInfoVector.size();i++){
                                FieldInfo current=(FieldInfo)fieldInfoVector.elementAt(i);
                                FieldInfo temp=new FieldInfo();
                                temp.fieldName=strColumnName;
                                temp.fieldParent=tobeRemoved;
                                boolean hasSyn=hasSynonymy(temp);
                                if (hasSyn){
                                    if (current.fieldName.equals(tobeRemoved+"."+strColumnName)) {
                                        fieldsVector.remove(current.fieldName);
                                        fieldInfoVector.remove(current);
                                    }
                                } else if (strColumnName.equals(current.fieldName)&&(tobeRemoved.equals(current.fieldParent))){
                                    fieldsVector.remove(strColumnName);
                                    fieldInfoVector.remove(current);
                                }
                            }
                            for (int i=0;i<criteriaVector.size();i++){
                                FieldInfo current=(FieldInfo)criteriaVector.elementAt(i);
                                FieldInfo temp=new FieldInfo();
                                temp.fieldName=strColumnName;
                                temp.fieldParent=tobeRemoved;
                                boolean hasSyn=hasSynonymy(temp);
                                if (hasSyn){
                                    if (current.fieldName.equals(tobeRemoved+"."+strColumnName)) {
                                        criteriaVector.remove(current);
                                        for (int j=0;j<dm.getRowCount();j++){
                                            if (current.fieldName.equals((String)dm.getValueAt(j,0))) dm.removeRow(j);
                                        }
                                    }
                                } else if (strColumnName.equals(current.fieldName)&&(tobeRemoved.equals(current.fieldParent))){
                                    criteriaVector.remove(current);
                                    for (int j=0;j<dm.getRowCount();j++){
                                        if (strColumnName.equals((String)dm.getValueAt(j,0))) dm.removeRow(j);
                                    }
                                }
                            }
                            bMore = rsColumns.next();
                        }
                        rsColumns.close();
                        
                    }catch(SQLException ex){}
                }
                
                fieldList.setListData(fieldsVector);
                tableList.setListData(tablesVector);
            }
        }
        
        //if Remove in the Field List is pressed
        else if (source==removeMenuItemF){
            String tobeRemoved=(String)fieldList.getSelectedValue();
            if (tobeRemoved!=null){
                fieldsVector.remove(tobeRemoved);
                fieldList.setListData(fieldsVector);
                String parent=new String();
                for (int i=0;i<fieldInfoVector.size();i++){
                    FieldInfo current=(FieldInfo)fieldInfoVector.elementAt(i);
                    if (current.fieldName.equals(tobeRemoved)) {
                        parent=current.fieldParent;
                        fieldInfoVector.remove(current);
                    }
                }
                boolean removeParent=true;
                
                for (int i=0;i<fieldInfoVector.size();i++){
                    FieldInfo current=(FieldInfo)fieldInfoVector.elementAt(i);
                    if (parent.equals(current.fieldParent)){
                        removeParent=false;
                        break;
                    }
                }
                if (removeParent){
                    for (int i=0;i<criteriaVector.size();i++){
                        FieldInfo current=(FieldInfo)criteriaVector.elementAt(i);
                        if (parent.equals(current.fieldParent)){
                            removeParent=false;
                            break;
                        }
                    }
                }
                /**if there are not any other fields from the same table either in the field list or in the criteria list,
                 * then remove this table from the tables list
                 */
                if (removeParent){
                    tablesVector.remove(parent);
                    tableList.setListData(tablesVector);
                }
            }
            // if "Remove WholeRow" is pressed in the criteria table
        } else if (source==removeMenuItemC){
            int position=criteriaTable.getSelectedRow();
            String tobeRemoved=(String)criteriaTable.getValueAt(position,0);
            if ((tobeRemoved!=null)&&(position!=-1)){
                dm.removeRow(position);
                criteriaTable.setModel(dm);
                FieldInfo fiRemove=(FieldInfo)criteriaVector.elementAt(position);
                String parent=fiRemove.fieldParent;
                criteriaVector.remove(position);
                boolean removeParent=true;
                
                for (int i=0;i<fieldInfoVector.size();i++){
                    FieldInfo current=(FieldInfo)fieldInfoVector.elementAt(i);
                    if (parent.equals(current.fieldParent)){
                        removeParent=false;
                        break;
                    }
                }
                if (removeParent){
                    for (int i=0;i<criteriaVector.size();i++){
                        FieldInfo current=(FieldInfo)criteriaVector.elementAt(i);
                        if (parent.equals(current.fieldParent)){
                            removeParent=false;
                            break;
                        }
                    }
                }
                /**if there are not any other fields from the same table either in the field list or in the criteria list,
                 * then remove this table from the tables list
                 */
                if (removeParent){
                    tablesVector.remove(parent);
                    tableList.setListData(tablesVector);
                }
                
            }
        }
        else if (source==removeMenuItemM){
            mapField.setText(null);
        }
        //if the map button is pressed
        else if ((source==mapButton)&&(ontPanel.ontModel!=null)){
            ontModel=ontPanel.ontModel;
            basePrefix=ontModel.getNsPrefixURI("");
            DatatypeProperty dp=ontPanel.ontModel.getDatatypeProperty(basePrefix+"queryString");
            String dbType=new String();
            if (dp!=null) dbType=dp.getLabel(null);
            if (tablesVector.size()==0){
                JOptionPane.showMessageDialog(null,"You haven't selected any data from the Database!",
                        "No Data Selected",
                        JOptionPane.ERROR_MESSAGE);
            } else if (fieldsVector.size()==0){
                JOptionPane.showMessageDialog(null,"You haven't selected any fields.\nIf you wish to add all the fields of the table,just drag and drop the table into the required tables area.",
                        "No Fields Selected",
                        JOptionPane.ERROR_MESSAGE);
            }else if (mapField.getText().equals("")){
                JOptionPane.showMessageDialog(null,"You haven't specified which class this data will be mapped to!",
                        "Map To Field Empty",
                        JOptionPane.ERROR_MESSAGE);
            } else if ((!dbType.equals(""))&&(!dbType.equals("PostgreSQL-"+parentPanel.databaseSelected))){
                JOptionPane.showMessageDialog(null,"You have loaded a file that contains mappings that refer to a different database from the one you are connected to!\n"+
                        "Try to open the correct database or remove all current mappings in order to begin a new mapping session.",
                        "Wrong Mappings File Loaded",
                        JOptionPane.ERROR_MESSAGE);
                
            } else{
                Vector inclForeign=new Vector();
                queryString=new String();
                queryString=queryString.concat("SELECT ");
                
                boolean needStar=true;
                //check if star is needed in the query
                try{
                    DatabaseMetaData dbMetaData =parentPanel.con.getMetaData();
                    Vector allFields=new Vector();
                    
                    for (int i=0;i<tablesVector.size();i++){
                        String tableName=(String)tablesVector.elementAt(i);
                        ResultSet rsColumns = dbMetaData.getColumns(null,null,tableName,null);
                        boolean bMore = rsColumns.next();
                        while (bMore) {
                            String strColumnName = rsColumns.getString("COLUMN_NAME");
                            FieldInfo fi=new FieldInfo();
                            fi.fieldName=strColumnName;
                            fi.fieldParent=tableName;
                            allFields.addElement(fi);
                            bMore=rsColumns.next();
                        }
                    }
                    for (int i=0;i<allFields.size();i++){
                        FieldInfo fi=(FieldInfo)allFields.elementAt(i);
                        String fieldName=fi.fieldName;
                        boolean hasSyn=hasSynonymy(fi);
                        if (hasSyn) fieldName=fi.fieldParent+"."+fi.fieldName;
                        if (!fieldsVector.contains(fieldName)){
                            needStar=false;
                            break;
                        }
                    }
                    if (fieldsVector.size()==0) needStar=true;
                }catch(SQLException ex){}
                
                //read the lists and form the query
                if (needStar) queryString=queryString.concat("*");
                else {
                    Iterator it=fieldsVector.iterator();
                    while (it.hasNext()){
                        queryString=queryString.concat((String)it.next());
                        if (it.hasNext()) queryString=queryString.concat(" , ");
                    }
                }
                queryString=queryString.concat(" FROM ");
                Iterator it2=tablesVector.iterator();
                while (it2.hasNext()){
                    queryString=queryString.concat((String)it2.next());
                    if (it2.hasNext()) queryString=queryString.concat(" , ");
                }
                Iterator it3=parentPanel.foreignKeys.iterator();
                Iterator it4;
                boolean needWhere=false;
                while (it3.hasNext()){
                    ForeignInfo currentForeign=(ForeignInfo)it3.next();
                    String fk_table=currentForeign.fk_table;
                    String pk_table=currentForeign.pk_table;
                    boolean foundfk=false;
                    boolean foundpk=false;
                    it4=tablesVector.iterator();
                    while (it4.hasNext()){
                        String currentTable=it4.next().toString();
                        if (fk_table.equals(currentTable)) foundfk=true;
                        else if (pk_table.equals(currentTable)) foundpk=true;
                    }
                    if (foundpk&&foundfk) {
                        inclForeign.addElement(currentForeign);
                        needWhere=true;
                    }
                    
                }

                //add WHERE only if there are criteria in the criteria table or if some foreign keys need to be taken into account
                if ((criteriaVector.size()>0)||needWhere){
                    queryString=queryString.concat(" WHERE ");
                    for (int j=0; j<inclForeign.size();j++ ){  
                        String fk_name=((ForeignInfo)inclForeign.elementAt(j)).fk_name;
                        String pk_name=((ForeignInfo)inclForeign.elementAt(j)).pk_name;
                        if (j!=0) queryString=queryString.concat("AND ");
                        queryString=queryString.concat("("+fk_name+"="+pk_name+") ");
                        if ((j==inclForeign.size()-1)&&(criteriaVector.size()!=0)) queryString=queryString.concat("AND ");
                        
                    }
                    
                    
                    String criteriaString=new String();
                    
                    for (int i=0;i<dm.getRowCount();i++) {
                        criteriaString=criteriaString.concat("(");
                        String currentField =(String)dm.getValueAt(i,0);
                        String currentCondition=(String)dm.getValueAt(i,1);
                        criteriaString=criteriaString.concat(currentField+currentCondition+")");
                        if (i!=dm.getRowCount()-1){
                            criteriaString=criteriaString.concat(" AND ");
                        }
                        
                    }
                    queryString=queryString.concat(criteriaString);
                }
                
                if (selectedNodeInfo.classInfo.type==ClassInfo.CLASS){
                    
                    ClassInfo classInfo=selectedNodeInfo.classInfo;
                    OntClass selectedClass=ontModel.getOntClass(basePrefix+mapField.getText());
                    Iterator data=ontModel.listDatatypeProperties();
                    boolean exists=false;
                    while (data.hasNext()){
                        if (((DatatypeProperty)data.next()).getLocalName().equals("queryString")) exists=true;
                    }
                    boolean mapAccepted=true;
                    boolean overWrite=true;
                    boolean alreadyMapped=false;
                    boolean queryAccepted=true;
                    
                    //check if mapping is accepted only when the queryString is legal
                    java.sql.Statement myStmt;
                    ResultSet ret = null;
                    try {
                        myStmt = parentPanel.con.createStatement();
                        ret = myStmt.executeQuery(queryString);
                    }catch (SQLException ex) {
                        JOptionPane.showMessageDialog(null,"Please check again your conditions. The following message has been thrown:\n"+ex.getMessage()+"\nREMINDER: Strings are enclosed in ' ' ",
                                "Error in data choosing",
                                JOptionPane.ERROR_MESSAGE);
                        queryAccepted=false;
                    }
                    
                    if (queryAccepted){
                        //check if mapping is accepted only when there is a queryString in the model
                        if (exists){
                            data=ontModel.listDatatypeProperties();
                            
                            while (data.hasNext()){
                                OntProperty prop=(OntProperty)data.next();
                                if ((prop.getLocalName().equals("queryString"))&&(prop.hasDomain(selectedClass))) alreadyMapped=true;
                            }
                            if (alreadyMapped){
                                overWrite=false;
                                int answer=JOptionPane.showConfirmDialog(null,"There is already a mapping for the given class.Do you want to replace it?",
                                        "Mapping exists",
                                        JOptionPane.YES_NO_OPTION);
                                if (answer==JOptionPane.YES_OPTION) overWrite=true;
                            }
                            
                            if (overWrite){
                                //execute the query stored in MapProperty and store results in a vector
                                Vector original=new Vector();
                                String origTableName=new String();
                                try {
                                    ResultSetMetaData rmeta=ret.getMetaData();
                                    
                                    
                                    int numColumns=rmeta.getColumnCount();
                                    
                                    while(ret.next()){
                                        for(int j=1;j<=numColumns;j++) {
                                            FieldInfo newFI=new FieldInfo();
                                            newFI.fieldName=ret.getString(j);
                                            newFI.fieldParent=rmeta.getColumnName(j);
                                            original.addElement(newFI);
                                        }
                                    }
                                }catch (SQLException ex) {}
                                
                                //check whether the mapping conforms with the ontology
                                
                                //check whether disjoint classes contain the same data
                                boolean disjAccepted=disjCheckMapDown(selectedClass,original);
                                if (disjAccepted) disjAccepted=disjCheckMapUp(selectedClass,original);
                                //check whether superclasses of the class being checked contain all of the data
                                boolean superAccepted=superCheckMap(selectedClass,original);
                                //check whether subclasses of the class being checked contain only data mapped to it
                                boolean subAccepted=subCheckMap(selectedClass,original);
                                //mapping is accepted only when all of the above checks are passed
                                mapAccepted = disjAccepted && superAccepted && subAccepted;
                            }
                            
                        }
                        //if the mapping is accepted then proceed by adding the property "queryString" to the selected class//if the mapping is accepted then proceed by adding the property "queryString" to the selected class
                        if (mapAccepted && overWrite){
                            DatatypeProperty odp=ontModel.createDatatypeProperty(basePrefix+"queryString",true);
                            
                            //remove previous mappings
                            if (alreadyMapped){
                                
                                int position=ontPanel.mapList.getNextMatch(selectedClass.getLocalName(),0,Position.Bias.Forward);
                                ontPanel.mapList.setSelectedIndex(position);
                                
                                String tobeRemoved=(String)ontPanel.mapList.getSelectedValue();
                                ontPanel.mapVector.removeElement(ontPanel.mapList.getSelectedValue());
                                ontPanel.mapList.setListData(ontPanel.mapVector);
                                
                                String basePrefix=ontModel.getNsPrefixURI("");
                                String classtoRemove=tobeRemoved.substring(0,tobeRemoved.indexOf('-'));
                                OntClass myClass= ontModel.getOntClass(basePrefix+classtoRemove);
                                OntProperty myProp = ontModel.getOntProperty(basePrefix+"queryString");
                                Property myProp2 = ontModel.getProperty(basePrefix,"queryString");
                                StmtIterator i = ontModel.listStatements(myClass, myProp2, (RDFNode)null);
                                
                                Vector tmp=new Vector();
                                while (i.hasNext()){
                                    com.hp.hpl.jena.rdf.model.Statement s = i.nextStatement();
                                    tmp.addElement(s.getSubject());
                                }
                                for (int j=0;j<tmp.size();j++){
                                    Resource res=(Resource)tmp.elementAt(j);
                                    res.removeAll(myProp);
                                    myProp.removeDomain(res);
                                }
                            }
                            
                            //sets the domain for property "queryString"
                            odp.addDomain(selectedClass);
                            //set the property value
                            selectedClass.setPropertyValue(odp, (RDFNode)(ontModel.createLiteral(queryString,null)));
                            //pass a timestamp as version info for this property
                            Calendar cal=Calendar.getInstance();
                            odp.setVersionInfo(cal.getTime().toString());
                            //save the database type and the database name in the property's label
                            odp.setLabel("PostgreSQL-"+parentPanel.databaseSelected,null);
                            //save the ontology file name as the property's comment
                            String localName=ontPanel.oldFilePath.substring(ontPanel.oldFilePath.lastIndexOf('\\')+1);
                            odp.setComment(localName,null);
                            
                            ontPanel.describeQuery(selectedClass.getLocalName(),queryString);
                            ontPanel.txtVersion.setText(odp.getVersionInfo());
                            ontPanel.txtDB.setText(odp.getLabel(null));
                            ontPanel.txtFile.setText(odp.getComment(null));
                        }
                    }
                } else if (selectedNodeInfo.classInfo.type==ClassInfo.THING){
                    JOptionPane.showMessageDialog(null,"You are trying to map data to Class Thing.\nTry to Drag and Drop another class.",
                            "Mapping to OWL:THING",
                            JOptionPane.WARNING_MESSAGE);
                } else if (selectedNodeInfo.type==NodeInfo.PROPERTY){
                    OntProperty selectedProp=ontModel.getOntProperty(mapField.getText());
                    
                    JOptionPane.showMessageDialog(null,"Property Mapping is not supported yet.\nTry to Drag and Drop a class",
                            "Property Mapping",
                            JOptionPane.WARNING_MESSAGE);
                }
                
                
            }
            
        } else if (ontPanel.ontModel==null){
            JOptionPane.showMessageDialog(null,"Please open an ontology first",
                    "No Ontology Loaded",
                    JOptionPane.ERROR_MESSAGE);
        }
    }
    
    //check whether disjoint classes (and their subclasses) contain the same data
    public boolean disjCheckMapDown(OntClass cls,Vector v){
       
        boolean mapAccepted=true;
        Iterator idis=cls.listDisjointWith();
        while (idis.hasNext()&&mapAccepted){
            OntClass cur=(OntClass)idis.next();
            OntProperty map=ontModel.getOntProperty(basePrefix+"queryString");
            
            mapAccepted=recurseDown(cur,map,cls,v);
        }
        
        return mapAccepted;
    }
    
    //recurse further down to the subclasses of cur and so on
    public boolean recurseDown (OntClass cur,OntProperty map,OntClass cls,Vector v){
        boolean mapAccepted=true;
        if (map.hasDomain(cur)){
                mapAccepted=compareData(cur,map,cls,v);
            }
            else {
                Iterator isub=ontPanel.ch.findSubclasses(cur);
                while (isub.hasNext()){
                    mapAccepted=recurseDown((OntClass)isub.next(),map,cls,v);
                    if (!mapAccepted) break;
                }
            }
        return mapAccepted;
    }
    
    
    //check whether disjoint classes (and their superclasses) contain the same data
    public boolean disjCheckMapUp(OntClass cls,Vector v){
        boolean mapAccepted=true;
        OntProperty map=ontModel.getOntProperty(basePrefix+"queryString");
        
        //recurse for the disjoints of the class's superclass
            Iterator isuper=ontPanel.ch.findSuperclasses(cls);
            while (isuper.hasNext()){
                OntClass cur=(OntClass)isuper.next();
                mapAccepted=recurseUp(cur,map,cls,v);
                if (!mapAccepted) break;
            }
        
        return mapAccepted;
    }
    
    //move up and check the disjoints of cur and their superclasses as well as the subclasses of every one of them
     public boolean recurseUp (OntClass cur,OntProperty map,OntClass cls,Vector v){
        boolean mapAccepted=true;
        Iterator idis=cur.listDisjointWith();
        while ((idis.hasNext())&&(mapAccepted)){
            OntClass current=(OntClass)idis.next();
            if (map.hasDomain(current)){
                mapAccepted=compareData(current,map,cls,v);
                if (!mapAccepted) break;
            }
            else {
                mapAccepted=recurseDown(current,map,cls,v);
                Iterator isuper=ontPanel.ch.findSuperclasses(current);
                while (isuper.hasNext()&&mapAccepted){
                    mapAccepted=recurseUp((OntClass)isuper.next(),map,cls,v);
                    if (!mapAccepted) break;
                }
            }
        }
        idis=cur.listDisjointWith();
        if (!idis.hasNext()){
            Iterator isuper=ontPanel.ch.findSuperclasses(cur);
            while (isuper.hasNext()&&mapAccepted){
                  mapAccepted=recurseUp((OntClass)isuper.next(),map,cls,v);
                  if (!mapAccepted) break;
              }
        }
        
        return mapAccepted;
    }
    
    //compare the data mapped to classes cur and cls 
    public boolean compareData(OntClass cur, OntProperty map,OntClass cls, Vector v ){
        boolean mapAccepted=true;
        StmtIterator i = ontModel.listStatements(cur, map, (RDFNode)null);
                while (i.hasNext()){
                    com.hp.hpl.jena.rdf.model.Statement s=i.nextStatement();
                    String execquery=s.getString();
                    ResultSet ret;
                    
                    /*
                     *execute the query for OntClass cur and store the results in another vector temp
                     */
                    try {
                        java.sql.Statement myStmt = parentPanel.con.createStatement();
                        ret = myStmt.executeQuery(execquery);
                        
                        ResultSetMetaData rmeta=ret.getMetaData();
                        int numColumns=rmeta.getColumnCount();
                        
                        Vector temp=new Vector();
                        
                        while(ret.next()){
                            for(int j=1;j<=numColumns;j++) {
                                FieldInfo newFI=new FieldInfo();
                                newFI.fieldName=ret.getString(j);
                                newFI.fieldParent=rmeta.getColumnName(j);
                                temp.addElement(newFI);
                            }
                        }
                        
                        //compare the two vectors
                        
                        for (int j=0;j<v.size();j++){
                            FieldInfo orcur =(FieldInfo)v.elementAt(j);
                            for (int k=0;k<temp.size();k++){
                                FieldInfo tempcur=(FieldInfo)temp.elementAt(k);
                                //map not accepted,because at least one cell of a table has been mapped to both classes.
                                //we need a table check as well,but getTableName returns null(bug in postgres)
                                if ((tempcur.fieldName.equals(orcur.fieldName))&&(tempcur.fieldParent.equals(orcur.fieldParent))){
                                    mapAccepted=false;
                                    break;
                                }
                                for (int l=0;l<parentPanel.foreignKeys.size();l++){
                                    ForeignInfo curFI=(ForeignInfo)parentPanel.foreignKeys.elementAt(l);
                                    //the class being checked has been mapped to data that belong in a foreign key column that points to a table mapped to a disjoint class
                                    //we need a table check again...
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.fk_name.equals(orcur.fieldParent))&&(curFI.pk_name.equals(tempcur.fieldParent))){
                                        mapAccepted=false;
                                        break;
                                    }
                                    //the class being checked has been mapped to data that belong in a foreign key column of a table that has been mapped to a disjoint class
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.pk_name.equals(orcur.fieldParent))&&(curFI.fk_name.equals(tempcur.fieldParent))){
                                        mapAccepted=false;
                                        break;
                                    }
                                }
                                
                            }
                            if (!mapAccepted){
                                JOptionPane.showMessageDialog(null,"Disjoint Classes can not have the same data mapped to them.\nClass "+cur.getLocalName()+" is disjoint with "+cls.getLocalName(),
                                        "Mapping Not Accepted", JOptionPane.ERROR_MESSAGE);
                                break;
                            }
                            
                            
                        }
                        
                    }catch (SQLException ex) {
                    }
                }
        return mapAccepted;
    }
    
    
    
    
    //check whether superclasses of the class being checked contain all of the data
    public boolean superCheckMap(OntClass cls,Vector v){
        
        boolean mapAccepted=true;
        Vector superChecked=new Vector();
        Iterator isuper = ontPanel.ch.findSuperclasses(cls);
        while (isuper.hasNext()&&mapAccepted){
            OntClass cur=(OntClass)isuper.next();
            OntProperty map=ontModel.getOntProperty(basePrefix+"queryString");
            
            //if this class has been mapped to a query
            if (map.hasDomain(cur)){
                superChecked.addElement(cur.getURI());
                StmtIterator i = ontModel.listStatements(cur, map, (RDFNode)null);
                while (i.hasNext()){
                    com.hp.hpl.jena.rdf.model.Statement s=i.nextStatement();
                    String execquery=s.getString();
                    ResultSet ret;
                    
                    /**for every superclass
                     *execute the query and store the results in another vector temp
                     */
                    try {
                        java.sql.Statement myStmt = parentPanel.con.createStatement();
                        ret = myStmt.executeQuery(execquery);
                        
                        ResultSetMetaData rmeta=ret.getMetaData();
                        int numColumns=rmeta.getColumnCount();
                        
                        Vector temp=new Vector();
                        
                        while(ret.next()){
                            for(int j=1;j<=numColumns;j++) {
                                FieldInfo newFI=new FieldInfo();
                                newFI.fieldName=ret.getString(j);
                                newFI.fieldParent=rmeta.getColumnName(j);
                                temp.addElement(newFI);
                            }
                        }
                        
                        //compare the two vectors
                        
                        for (int j=0;j<v.size();j++){
                            FieldInfo orcur =(FieldInfo)v.elementAt(j);
                            boolean dataFound=false;
                            for (int k=0;k<temp.size();k++){
                                FieldInfo tempcur=(FieldInfo)temp.elementAt(k);
                                if ((tempcur.fieldName.equals(orcur.fieldName))&&(tempcur.fieldParent.equals(orcur.fieldParent))){
                                    dataFound=true;
                                    break;
                                }
                                for (int l=0;l<parentPanel.foreignKeys.size();l++){
                                    ForeignInfo curFI=(ForeignInfo)parentPanel.foreignKeys.elementAt(l);
                                    //the class being checked has been mapped to data that belong in a foreign key column that points to a table mapped to a superclass
                                    //we need a table check again...
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.fk_name.equals(orcur.fieldParent))&&(curFI.pk_name.equals(tempcur.fieldParent))){
                                        dataFound=true;
                                        break;
                                    }
                                    //the class being checked has been mapped to data that belong in a foreign key column of a table that has been mapped to a superclass
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.pk_name.equals(orcur.fieldParent))&&(curFI.fk_name.equals(tempcur.fieldParent))){
                                        dataFound=true;
                                        break;
                                    }
                                }
                            }
                            //map not accepted,because at least one cell of a table is not found on the data mapped to one of the superclasses
                            if (!dataFound) mapAccepted=false;
                            if (!mapAccepted){
                                JOptionPane.showMessageDialog(null,"Subclasses must contain no data that are different from the ones mapped to their superclasses.\nClass "+cls.getLocalName()+" is subclass of "+cur.getLocalName(),
                                        "Mapping Not Accepted", JOptionPane.ERROR_MESSAGE);
                                break;
                            }
                            
                            
                        }
                        
                    }catch (SQLException ex) {
                    }
                }
            }
            
        }
        //at the end, recurse for (indirect) superclasses
        if (mapAccepted){
            isuper=ontPanel.ch.findSuperclasses(cls);
            while (isuper.hasNext()){
                OntClass cur=(OntClass)isuper.next();
                if (!superChecked.contains(cur.getURI())) mapAccepted=superCheckMap(cur,v);
                if (!mapAccepted) break;
            }
        }
        return mapAccepted;
    }
    
    //check whether subclasses of the class being checked contain only data mapped to it
    public boolean subCheckMap(OntClass cls,Vector v){
        
        boolean mapAccepted=true;
        Vector subChecked=new Vector();
        Iterator isub = ontPanel.ch.findSubclasses(cls);
        while (isub.hasNext()&&mapAccepted){
            OntClass cur=(OntClass)isub.next();
            OntProperty map=ontModel.getOntProperty(basePrefix+"queryString");
            
            //if this class has been mapped to a query
            if (map.hasDomain(cur)){
                subChecked.addElement(cur.getURI());
                StmtIterator i = ontModel.listStatements(cur, map, (RDFNode)null);
                while (i.hasNext()){
                    com.hp.hpl.jena.rdf.model.Statement s=i.nextStatement();
                    String execquery=s.getString();
                    ResultSet ret;
                    
                    /**for every subclass
                     *execute the query and store the results in another vector temp
                     */
                    try {
                        java.sql.Statement myStmt = parentPanel.con.createStatement();
                        ret = myStmt.executeQuery(execquery);
                        
                        ResultSetMetaData rmeta=ret.getMetaData();
                        String tempTableName =rmeta.getTableName(1);
                        int numColumns=rmeta.getColumnCount();
                        
                        Vector temp=new Vector();
                        
                        while(ret.next()){
                            for(int j=1;j<=numColumns;j++) {
                                FieldInfo newFI=new FieldInfo();
                                newFI.fieldName=ret.getString(j);
                                newFI.fieldParent=rmeta.getColumnName(j);
                                temp.addElement(newFI);
                            }
                        }
                        
                        //compare the two vectors
                        
                        for (int j=0;j<temp.size();j++){
                            FieldInfo tempcur =(FieldInfo)temp.elementAt(j);
                            boolean dataFound=false;
                            for (int k=0;k<v.size();k++){
                                FieldInfo orcur=(FieldInfo)v.elementAt(k);
                                if ((tempcur.fieldName.equals(orcur.fieldName))&&(tempcur.fieldParent.equals(orcur.fieldParent))){
                                    dataFound=true;
                                    break;
                                }
                                for (int l=0;l<parentPanel.foreignKeys.size();l++){
                                    ForeignInfo curFI=(ForeignInfo)parentPanel.foreignKeys.elementAt(l);
                                    //the class being checked has been mapped to data that belong in a foreign key column that points to a table mapped to a subclass
                                    //we need a table check again...
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.fk_name.equals(orcur.fieldParent))&&(curFI.pk_name.equals(tempcur.fieldParent))){
                                        dataFound=true;
                                        break;
                                    }
                                    //the class being checked has been mapped to data that belong in a foreign key column of a table that has been mapped to a subclass
                                    if ((tempcur.fieldName.equals(orcur.fieldName))&&(curFI.pk_name.equals(orcur.fieldParent))&&curFI.fk_name.equals(tempcur.fieldParent)){
                                        dataFound=true;
                                        break;
                                    }
                                }
                            }
                            //map not accepted,because at least one cell of a table mapped to a subclass is not mapped to the class being checked
                            if (!dataFound) mapAccepted=false;
                            if (!mapAccepted){
                                JOptionPane.showMessageDialog(null,"Superclasses must contain all the data that have been mapped to their subclasses.\nClass "+cls.getLocalName()+" is superclass of "+cur.getLocalName(),
                                        "Mapping Not Accepted", JOptionPane.ERROR_MESSAGE);
                                break;
                            }
                            
                            
                        }
                        
                    }catch (SQLException ex) {
                    }
                }
            }
            
        }
        
        //at the end,recurse for (indirect) subclasses
        if (mapAccepted){
            isub=ontPanel.ch.findSubclasses(cls);
            while (isub.hasNext()){
                OntClass cur=(OntClass)isub.next();
                if (!subChecked.contains(cur.getURI())) mapAccepted=subCheckMap(cur,v);
                if (!mapAccepted) break;
            }
        }
        return mapAccepted;
    }
    
    
    
    public void drop(DropTargetDropEvent event) {
        
        try {
            Transferable transferable = event.getTransferable();
            // we accept only Strings
            if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)){
                
                event.getDropTargetContext().dropComplete(true);
                
                
                if (event.getDropTargetContext().getComponent()==tableList){
                    
                    JTree treeTables=parentPanel.treeTables;
                    String s = (String)transferable.getTransferData( DataFlavor.stringFlavor);
                    DefaultMutableTreeNode node=(DefaultMutableTreeNode)treeTables.getLastSelectedPathComponent();
                    String nodeName=((TreeNodeInfo)node.getUserObject()).toString();
                    DefaultMutableTreeNode parentNode=(DefaultMutableTreeNode)node.getParent();
                    Enumeration children = node.children();
                    TreeNodeInfo parentName=(TreeNodeInfo)parentNode.getUserObject();
                    
                    //search the table list to check if the dragged table is already in the list
                    if (parentName.toString().equals("Data Source")){
                        
                        int answer=JOptionPane.showConfirmDialog(null,"You have chosen to insert a whole table in the list. This will add all of its fields in the desired fields list.\nDo you want to continue?",
                                "Inserting In Table List",
                                JOptionPane.YES_NO_OPTION);
                        
                        if (answer==JOptionPane.YES_OPTION){
                            
                            if (!tablesVector.contains(nodeName)) tablesVector.addElement(nodeName);
                            //add in the fields list all the fields of the added table (that are not yet added)
                            while (children.hasMoreElements()){
                                DefaultMutableTreeNode child =(DefaultMutableTreeNode)children.nextElement();
                                TreeNodeInfo childInfo = (TreeNodeInfo)child.getUserObject();
                                String fieldName=childInfo.toString();
                                fieldName = fixFieldsName(fieldName);
                                FieldInfo fieldInfo=new FieldInfo();
                                fieldInfo.fieldName=fieldName;
                                fieldInfo.fieldParent=nodeName;
                                
                                boolean hasSyn=hasSynonymy(fieldInfo);
                                if (hasSyn){
                                    String newName=fieldInfo.fieldParent+"."+fieldInfo.fieldName;
                                    fieldInfo.fieldName=newName;
                                }
                                
                                //add to the field list all the fields of the table dragged, unless they are already in it
                                Iterator i=fieldInfoVector.iterator();
                                boolean alreadyThere=false;
                                while(i.hasNext()){
                                    FieldInfo current =(FieldInfo)i.next();
                                    
                                    if (fieldInfo.fieldName.equals(current.fieldName)) alreadyThere=true;
                                }
                                if (!alreadyThere){
                                    fieldInfoVector.addElement(fieldInfo);
                                    fieldsVector.addElement(fieldInfo.fieldName);
                                }
                                
                            }
                        }
                        tableList.setListData(tablesVector);
                        fieldList.setListData(fieldsVector);
                        
                    } else {
                        JOptionPane.showMessageDialog(null,"Please drop only tables from the database in this field",
                                "No Table Dragged",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
                
                else if (event.getDropTargetContext().getComponent()==fieldList){
                    JTree treeTables=parentPanel.treeTables;
                    String s = (String)transferable.getTransferData( DataFlavor.stringFlavor);
                    DefaultMutableTreeNode node=(DefaultMutableTreeNode)treeTables.getLastSelectedPathComponent();
                    DefaultMutableTreeNode parentNode=(DefaultMutableTreeNode)node.getParent();
                    TreeNodeInfo parentName=(TreeNodeInfo)parentNode.getUserObject();
                    //accept only columns dropped
                    if (!parentName.toString().equals("Data Source")){
                        s=fixFieldsName(s);
                        FieldInfo fieldInfo=new FieldInfo();
                        fieldInfo.fieldName=s;
                        fieldInfo.fieldParent=parentName.toString();
                        
                        
                        //add the table this fields belongs to the table list,unless it already exists
                        if (!tablesVector.contains(parentName.toString())) {
                            tablesVector.addElement(parentName.toString());
                        }
                        
                        //add in front of every field name that has a synonymy,its parent table name
                        boolean hasSyn=hasSynonymy(fieldInfo);
                        if (hasSyn){
                            String newName=fieldInfo.fieldParent+"."+fieldInfo.fieldName;
                            fieldInfo.fieldName=newName;
                        }
                        
                        //search the field list to check if the dragged field is already in the list
                        Iterator i=fieldInfoVector.iterator();
                        boolean isAlready=false;
                        while(i.hasNext()){
                            FieldInfo current =(FieldInfo)i.next();
                            if (fieldInfo.fieldName.equals(current.fieldName)) isAlready=true;
                        }
                        if (!isAlready){
                            fieldInfoVector.addElement(fieldInfo);
                            fieldsVector.addElement(fieldInfo.fieldName);
                        }
                        fieldList.setListData(fieldsVector);
                        tableList.setListData(tablesVector);
                    } else {
                        JOptionPane.showMessageDialog(null,"Please drop only columns from the database in this field",
                                "No Column Dragged",
                                JOptionPane.ERROR_MESSAGE);
                    }
                    
                }
                
                else if ((event.getDropTargetContext().getComponent()==scrollTable)||(event.getDropTargetContext().getComponent()==criteriaTable)){
                    
                    JTree treeTables=parentPanel.treeTables;
                    String s = (String)transferable.getTransferData( DataFlavor.stringFlavor);
                    DefaultMutableTreeNode node=(DefaultMutableTreeNode)treeTables.getLastSelectedPathComponent();
                    DefaultMutableTreeNode parentNode=(DefaultMutableTreeNode)node.getParent();
                    TreeNodeInfo parentName=(TreeNodeInfo)parentNode.getUserObject();
                    //accept only columns dropped
                    if (!parentName.toString().equals("Data Source")){
                        s=fixFieldsName(s);
                        FieldInfo fieldInfo=new FieldInfo();
                        fieldInfo.fieldName=s;
                        fieldInfo.fieldParent=parentName.toString();
                        
                        
                        boolean hasSyn=hasSynonymy(fieldInfo);
                        if (hasSyn){
                            String newName=fieldInfo.fieldParent+"."+fieldInfo.fieldName;
                            fieldInfo.fieldName=newName;
                        }
                        
                        
                        criteriaVector.addElement(fieldInfo);
                        Vector temp = new Vector();
                        temp.addElement(fieldInfo.fieldName);
                        dm.addRow(temp);
                        criteriaTable.setModel(dm);
                        
                        //add the table to which this field belongs to the table list as well
                        if (!tablesVector.contains(parentName.toString()))
                            tablesVector.addElement(parentName.toString());
                        tableList.setListData(tablesVector);
                        
                    }
                    else {
                        JOptionPane.showMessageDialog(null,"Please drop only columns from the database in this field",
                            "No Column Dragged",
                            JOptionPane.ERROR_MESSAGE);
                    }
                }
                //drop the ontlogy class to the map field
                else if (event.getDropTargetContext().getComponent()==mapField){
                    JTree ontTree=ontPanel.ontTree;
                    DefaultTreeModel tm=(DefaultTreeModel)ontTree.getModel();
                    DefaultMutableTreeNode selectedNode=(DefaultMutableTreeNode)ontTree.getLastSelectedPathComponent();
                    selectedNodeInfo=(NodeInfo)selectedNode.getUserObject();
                    String s = selectedNodeInfo.toString();
                    mapField.setText(s);
                }else{
                    event.rejectDrop();
                }
                
            } else{
                event.rejectDrop();
            }
        } catch (IOException exception) {
            exception.printStackTrace();
            System.err.println( "Exception" + exception.getMessage());
            event.rejectDrop();
        } catch (UnsupportedFlavorException ufException ) {
            ufException.printStackTrace();
            System.err.println( "Exception" + ufException.getMessage());
            event.rejectDrop();
        } catch (Exception ex){
            JOptionPane.showMessageDialog(null,"Please drop only columns from the database in this field",
                            "No Column Dragged",
                            JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /* cut the parentheses (which indicate the transformation of protege data types to sql types)
     * from the columns name taken by the tree
     */
    public String fixFieldsName(String s){
        int fb=s.indexOf('(');
        s=s.substring(0,fb-1);
        return s;
    }
    
    public void dragExit(DropTargetEvent event) {
        //System.out.println( "dragExit");
    }
    
    public void dropActionChanged( DropTargetDragEvent event ) {
    }
    
    
    public void dragOver(DropTargetDragEvent event) {
        // System.out.println( "dragOver");
    }
    
    public void dragEnter(DropTargetDragEvent event) {
        
        // debug messages for diagnostics
        //System.out.println( "dragEnter");
        //event.acceptDrag(DnDConstants.ACTION_MOVE);
    }
    
     /* check if a field of a table has synonymy with one of another table.
      *If there is a synonymy,add in front of the field's name the table's name it belongs to
      */
    public boolean hasSynonymy(FieldInfo f){
        
        String parentName=f.fieldParent;
        String name=f.fieldName;
        DefaultTreeModel treeModel=parentPanel.treeModel;
        boolean hasSyn=false;
        
        DefaultMutableTreeNode root=(DefaultMutableTreeNode)treeModel.getRoot();
        int tablesCount=treeModel.getChildCount(root);
        
        for (int i=0;i<tablesCount;i++){
            DefaultMutableTreeNode currentTable=(DefaultMutableTreeNode)treeModel.getChild(root,i);
            TreeNodeInfo tableNode=(TreeNodeInfo)(currentTable).getUserObject();
            String tableName=tableNode.toString();
            if (!tableName.equals(parentName)){
                int fieldsCount=treeModel.getChildCount(treeModel.getChild(root,i));
                for (int j=0;j<fieldsCount;j++){
                    DefaultMutableTreeNode currentField=(DefaultMutableTreeNode) treeModel.getChild(currentTable,j);
                    String fieldName=((TreeNodeInfo)currentField.getUserObject()).toString();
                    fieldName=fixFieldsName(fieldName);
                    if (fieldName.equals(name)) hasSyn=true;
                }
            }
        }
        return hasSyn;
        
    }
    
}


class FieldInfo {
    
    String fieldName;
    String fieldParent;
}

//A listener to components that can bring up popup menus.
class PopupListener extends MouseAdapter {
    
    JPopupMenu popup;
    JList listT;
    JTable tableT;
    Point point = new Point(0,0);
    
    PopupListener(JPopupMenu popupMenu) {
        popup = popupMenu;
    }
    
    PopupListener(JPopupMenu popupMenu,JList tableList) {
        popup = popupMenu;
        listT=tableList;
    }
    
    PopupListener(JPopupMenu popupMenu,JTable table) {
        popup = popupMenu;
        tableT=table;
    }
    
    public void mousePressed(MouseEvent e) {
        maybeShowPopup(e);
    }
    
    public void mouseReleased(MouseEvent e) {
        maybeShowPopup(e);
    }
    
    private void maybeShowPopup(MouseEvent e) {
        if (listT!=null){
            boolean empty=listT.isSelectionEmpty();
            if (!empty) {
                point = listT.indexToLocation(listT.getSelectedIndex());
                if (e.isPopupTrigger()) {
                    popup.show(e.getComponent(),e.getX(), (int)point.getY());
                }
            }
        } else if (tableT!=null){
            int rowIndex=tableT.getSelectedRow();
            if (rowIndex!=-1){
                if (e.isPopupTrigger()) {
                    popup.show(e.getComponent(),e.getX(), (int)tableT.getRowHeight()*rowIndex);
                }
            }
        }
        else{
            if (e.isPopupTrigger()) {
                    popup.show(e.getComponent(),e.getX(), e.getY());
                }
        }
    }
}


